/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package be.darling.scrt.configuration;

import be.darling.scrt.data.Reader;
import be.darling.scrt.generator.Generator;
import be.darling.scrt.statistics.Statistic;
import com.djahva.pax.Collector;
import com.djahva.pax.DOMReader;
import com.djahva.pax.HashMapReader;
import com.djahva.pax.PaxReader;
import com.djahva.pax.StringReader;
import com.djahva.pax.XMLPosition;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.w3c.dom.Node;

/**
 *
 * @author jingle
 */
public class Configuration {

    private File configFile;
    private HashMap<String, PluginData> designs = new HashMap<String, PluginData>();
    private HashMap<String, PluginData> dataReaders = new HashMap<String, PluginData>();
    private HashMap<String, PluginData> statistics = new HashMap<String, PluginData>();

    private String output;

    private Long defaultMaxTotalIterations;
    private Long defaultMaxRandomIterations;
    private double factor;

    public Configuration(File configFile)
    {

        this.configFile = configFile;


        PaxReader pax = new PaxReader();


        class PluginReader extends HashMapReader{
            HashMap dest;
            PluginReader(HashMap dest) {
                this.dest = dest;
            }
            protected void save(XMLPosition xmlPosition, String s) {

                PluginData pl = new PluginData((String)values.get("type"), (String)values.get("name"), (String)values.get("className"), (HashMap<String, String>)values.get("options"), (Node)values.get("DOMOptions") );
                dest.put(pl.getType(),pl);
            }
        }

        pax.addReader(new HashMapReader(), "randomizationTestOptions/options", "configOptions");

        pax.addReader(new PluginReader(dataReaders){ }, "data/reader", "readerReader");
        pax.addReader(new HashMapReader(), "data/reader/options", "options")
                .setDestination((Collector) pax.getReader("readerReader"));
        pax.addReader(new DOMReader(), "data/reader/options", "DOMOptions")
                .setDestination((Collector)pax.getReader("readerReader"));

        pax.addReader(new PluginReader(designs),"design", "designReader");
        pax.addReader(new HashMapReader(), "design/options","options")
                .setDestination((Collector) pax.getReader("designReader"));
        pax.addReader(new DOMReader(), "design/options", "DOMOptions")
                .setDestination((Collector)pax.getReader("designReader"));


        pax.addReader(new PluginReader(statistics),"statistic", "statisticReader");
        pax.addReader(new HashMapReader(), "statistic/options", "options")
                .setDestination((Collector) pax.getReader("statisticReader"));
        pax.addReader(new DOMReader(), "statistic/options", "DOMOptions")
                .setDestination((Collector)pax.getReader("statisticReader"));


        pax.parse(configFile);

        HashMap hMap = (HashMap)pax.get("configOptions");
        output = (String)hMap.get("output");
        defaultMaxTotalIterations = Long.parseLong( (String)hMap.get("defaultMaxTotalIterations") );
        defaultMaxRandomIterations = Long.parseLong( (String)hMap.get("defaultMaxRandomIterations") );
        factor = Double.parseDouble( (String)hMap.get("factor") );
    }

    public String getOutput() {
        return output;
    }

    /**
     * Get the number of iterations as configured in the configuration file under the 
     * tag defaultMaxTotalIterations.
     * @return defaultMaxTotalIterations
     */
    public Long getDefaultIterations() {     //necessary??
        return defaultMaxTotalIterations;
    }

    /**
     * Get the factor by which the defaultMaxTotalIterations are multiplied to get the iterations if
     * the iterations are nowwhere else specified.
     * @return
     */
    public double getFactor() {        //necessary??
        return factor;
    }

    /**
     * Get factor * defaultMaxTotalIterations. This number is used if the number of iterations is nowwhere else
     * specified (e.g. in the options of the design(s)).
     * @return factor*defaultMaxTotalIterations
     */
    public Long getMaxTotalIterations()
    {
        Double d = factor * defaultMaxTotalIterations;
        return d.longValue();
    }

    public Long getMaxRandomIterations()
    {
        Double d = factor * defaultMaxRandomIterations;
        return d.longValue();
    }

    public Generator getGenerator(String type)
    {
        PluginData plug = designs.get(type);
        Generator gen = (Generator)getObject(designs.get(type) );
        gen.setOptions( (HashMap)plug.getOptions(HashMap.class));
        gen.setOptions( (Node)plug.getOptions(Node.class));
        gen.setDescription( plug.getDescription() );
        gen.setName( plug.getName() );
        gen.init();
        return gen;
    }

    public Statistic getStatistic(String type)
    {
        PluginData plug = statistics.get(type);
        Statistic stat = (Statistic)getObject(statistics.get(type) );
        stat.setName( plug.getName() );
        stat.setDescription(plug.getDescription());
        stat.setOptions( (Node)plug.getOptions(Node.class));
        stat.setOptions( (HashMap)plug.getOptions(HashMap.class));
        stat.init();
        return stat;
    }

    public Reader getDataReader(String type)
    {
        PluginData plug = dataReaders.get(type);
        Reader reader = (Reader)getObject( plug );
        reader.setOptions( (HashMap)plug.getOptions(HashMap.class));
        reader.setOptions( (Node)plug.getOptions(Node.class));
        reader.setName(plug.getName());
        reader.setDescription(plug.getDescription());
        reader.init();
        return reader;
    }

    public List<String> listStatistics()  {
        return  new ArrayList<String>(this.statistics.keySet());

    }

    public List<String> listDesigns()
    {
        return  new ArrayList<String>(this.designs.keySet());
    }

    public List<String> listReaders()
    {
        return  new ArrayList<String>(this.dataReaders.keySet());
    }

    private Object getObject(PluginData plugInData)
    {
        Object obj = null;
        try {
            Class cl = Class.forName(plugInData.getClassName());
            obj = cl.newInstance();
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch(IllegalAccessException e) {
            e.printStackTrace();
        }

        return obj;
    }

    public static void main(String[] args) {
        Configuration conf = new Configuration(new File("conf/randomizationTest.xml"));

        List<String> statTypes = conf.listStatistics();
        System.out.println("Stat Types: "+ statTypes);
        System.out.println("Design Types: "+ conf.listDesigns());
        System.out.println("DataReader Types: "+ conf.listReaders());

        Statistic stat = conf.getStatistic("meansDifference");
    }


}
